package utils

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sync"
)

var SignFunLocks = map[string]*sync.Mutex{}

func IsContain(items []string, item string) bool {
	for _, eachItem := range items {
		if eachItem == item {
			return true
		}
	}
	return false
}

func SignFun(lockName string, exec func(), lockCallback func()) {
	mutex := SignFunLocks[lockName]
	if mutex == nil {
		mutex = &sync.Mutex{}
		SignFunLocks[lockName] = mutex
	}
	if mutex.TryLock() {
		defer func() {
			mutex.Unlock()
		}()
		exec()
	} else {
		lockCallback()
	}
}

// FileExist  文件是否存在
func FileExist(file interface{}) bool {
	if s, ok := file.(string); ok {
		_, err := os.Stat(s)
		return err == nil
	} else {
		return false
	}
}

// RunCommand 打印命令输出
func RunCommand(path string, command string, arg ...string) bool {
	if command == "" {
		return true
	}
	var cmd *exec.Cmd
	if runtime.GOOS == "windows" {
		cmd = exec.Command("cmd", append([]string{"/C", command}, arg...)...)
	} else {
		cmd = exec.Command(command, arg...)
	}
	if path != "" {
		cmd.Dir = path
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Println("stdout 命令:", command, arg, "执行异常:", err)
		return false
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Println("stderr 命令:", command, arg, "执行异常:", err)
		return false
	}
	if err := cmd.Start(); err != nil {
		log.Println("start 命令:", command, "执行异常:", err)
		return false
	}
	go printOutput(stdout)
	go printOutput(stderr)
	if err := cmd.Wait(); err != nil {
		log.Println("wait命令:", command, "执行异常:", err)
		return false
	}
	return true
}

func RunScript(path string, command string) bool {
	if command == "" {
		return true
	}
	var cmd *exec.Cmd
	if runtime.GOOS == "windows" {
		cmd = exec.Command("cmd", "/C", command)
	} else {
		cmd = exec.Command("bash", command)
	}
	if path != "" {
		cmd.Dir = path
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Println("stdout命令:", command, "执行异常:", err)
		return false
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Println("stderr命令:", command, "执行异常:", err)
		return false
	}
	if err := cmd.Start(); err != nil {
		log.Println("start命令:", command, "执行异常:", err)
		return false
	}
	go printOutput(stdout)
	go printOutput(stderr)
	if err := cmd.Wait(); err != nil {
		log.Println("wait命令:", command, "执行异常:", err)
		return false
	}

	return true
}

func printOutput(reader io.ReadCloser) {
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "error reading output:", err)
	}
}

func BinAbsPath() string {
	ex, err := os.Executable()
	if err != nil {
		panic(err)
	}
	return filepath.Dir(ex)
}

func BinRunPath() string {
	dir, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return dir
}
